package common

import (
	"fmt"

	"github.com/nacos-group/nacos-sdk-go/v2/clients"
	"github.com/nacos-group/nacos-sdk-go/v2/clients/config_client"
	"github.com/nacos-group/nacos-sdk-go/v2/clients/naming_client"
	"github.com/nacos-group/nacos-sdk-go/v2/common/constant"
	"github.com/nacos-group/nacos-sdk-go/v2/model"
	"github.com/nacos-group/nacos-sdk-go/v2/vo"
)

// 定义常量和一些参数默认值
var (
	clientParam              vo.NacosClientParam // 客户端参数缓存
	nacosIp                  = "127.0.0.1"
	nacosPort                = uint64(8848)
	nacosContextPath         = "/nacos"
	nacosNamespaceId         string
	nacosTimeout             = uint64(5000)
	nacosNotLoadCacheAtStart = true
	nacosLogDir              = "nacos/log"
	nacosCacheDir            = "nacos/cache"
	nacosLogLevel            = "debug"
)

// 结构体
type NacosParams struct {
	NacosIp                  string
	NacosPort                uint64
	NacosContextPath         string
	NacosNamespaceId         string
	NacosTimeoutMs           uint64
	NacosNotLoadCacheAtStart bool
	NacosLogDir              string
	NacosCacheDir            string
	NacosLogLevel            string
}

// nacos参数实例
var nacosParams NacosParams = NacosParams{
	NacosIp:                  nacosIp,
	NacosPort:                nacosPort,
	NacosContextPath:         nacosContextPath,
	NacosNamespaceId:         nacosNamespaceId,
	NacosTimeoutMs:           nacosTimeout,
	NacosNotLoadCacheAtStart: nacosNotLoadCacheAtStart,
	NacosLogDir:              nacosLogDir,
	NacosCacheDir:            nacosCacheDir,
	NacosLogLevel:            nacosLogLevel,
}

// InitConfig 初始化配置，允许通过函数参数修改默认配置
func InitNacosParams(paramsModifier func(*NacosParams)) {
	if paramsModifier != nil {
		paramsModifier(&nacosParams)
	}
}

// 获取当前参数
func GetNacosCurrentParams() NacosParams {
	return nacosParams
}

// 获取 nacos客户端参数
func getNacosClientParam() vo.NacosClientParam {
	// 缓存配置参数
	if clientParam.ClientConfig != nil {
		return clientParam
	}
	// create ServerConfig
	sc := []constant.ServerConfig{
		*constant.NewServerConfig(nacosParams.NacosIp, nacosParams.NacosPort, constant.WithContextPath(nacosParams.NacosContextPath)),
	}
	// create ClientConfig
	cc := *constant.NewClientConfig(
		constant.WithNamespaceId(nacosParams.NacosNamespaceId),
		constant.WithTimeoutMs(nacosParams.NacosTimeoutMs),
		constant.WithNotLoadCacheAtStart(nacosParams.NacosNotLoadCacheAtStart),
		constant.WithLogDir(nacosParams.NacosLogDir),
		constant.WithCacheDir(nacosParams.NacosCacheDir),
		constant.WithLogLevel(nacosParams.NacosLogLevel),
	)
	clientParam = vo.NacosClientParam{
		ClientConfig:  &cc,
		ServerConfigs: sc,
	}
	return clientParam
}

// 获取 NacosNamingClient
func getNacosNamingClient() (naming_client.INamingClient, error) {
	return clients.NewNamingClient(getNacosClientParam())
}

// 获取 NacosConfigClient
func getNacosConfigClient() (config_client.IConfigClient, error) {
	return clients.NewConfigClient(getNacosClientParam())
}

// 注册服务功能
func NacosRegisterServiceInstance(param vo.RegisterInstanceParam) (bool, error) {
	client, err := getNacosNamingClient()
	if err != nil {
		fmt.Println("getNacosNamingClient Error", err.Error())
		return false, err
	}
	return client.RegisterInstance(param)
}

// 获取服务
func NacosGetService(param vo.GetServiceParam) (model.Service, error) {
	client, err := getNacosNamingClient()
	if err != nil {
		fmt.Println("getNacosNamingClient Error", err.Error())
		return model.Service{}, err
	}
	return client.GetService(param) // service, err
}

// 获取所有服务
func NacosGetAllService(param vo.GetAllServiceInfoParam) (model.ServiceList, error) {
	client, err := getNacosNamingClient()
	if err != nil {
		fmt.Println("getNacosNamingClient Error", err.Error())
		return model.ServiceList{}, err
	}
	return client.GetAllServicesInfo(param)
}

// 获取远程配置
func NacosGetConfig(dataId string, group string) (string, error) {
	client, err := getNacosConfigClient()
	if err != nil {
		fmt.Println("getNacosNamingClient Error", err.Error())
		return "", err
	}
	return client.GetConfig(vo.ConfigParam{
		DataId: dataId,
		Group:  group,
	})
}

// 搜索配置文件
func NacosSearchConfig(params vo.SearchConfigParam) (*model.ConfigPage, error) {
	client, err := getNacosConfigClient()
	if err != nil {
		fmt.Println("NacosGetConfig Error", err.Error())
		return nil, err
	}
	return client.SearchConfig(params)
}

// 监听远程配置改动 回调函数类型
type ConfigChangeListener func(namespace, group, dataId, data string)

// 监听远程配置改动
func NacosListenConfigWithCallback(dataId, group string, onChange ConfigChangeListener) error {
	client, err := getNacosConfigClient()
	if err != nil {
		fmt.Println("getNacosNamingClient Error", err.Error())
		return err
	}
	err = client.ListenConfig(vo.ConfigParam{
		DataId: dataId,
		Group:  group,
		OnChange: func(namespace, group, dataId, data string) {
			// 当配置变更时，调用传入的回调函数
			onChange(namespace, group, dataId, data)
		},
	})
	return err
}
